﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Practices.Prism.Events;
using Reactor.Entities;
using Reactor.Messages.Events.Adoptions;
using Reactor.MiniManager.Events;
using Reactor.Providers;

namespace Reactor.MiniManager.ViewModels
{
    public class CoreServicesViewModel : ViewModelBase
    {
        private readonly ICoreDataProvider _coreDataProvider;
        private readonly ReactorCoreEntity _reactorCoreEntity;

        /// <summary>
        /// Initializes a new instance of the <see cref="CoreServicesViewModel"/> class.
        /// </summary>
        /// <param name="eventAggregator">The event aggregator.</param>
        /// <param name="coreDataProvider">The core data provider.</param>
        /// <param name="reactorCoreEntity">The reactor core entity.</param>
        public CoreServicesViewModel(IEventAggregator eventAggregator, ICoreDataProvider coreDataProvider, ReactorCoreEntity reactorCoreEntity)
        {
            if (eventAggregator == null) throw new ArgumentNullException("eventAggregator");
            if (coreDataProvider == null) throw new ArgumentNullException("coreDataProvider");
            if (reactorCoreEntity == null) throw new ArgumentNullException("reactorCoreEntity");

            _coreDataProvider = coreDataProvider;
            _reactorCoreEntity = reactorCoreEntity;
            Services = new ObservableCollection<ServiceViewModel>();

            eventAggregator.GetEvent<ServiceOrphanedEventReceived>().Subscribe(HandleServiceOrhanedEvent);

            Task.Factory.StartNew(LoadServices);
        }

        public ObservableCollection<ServiceViewModel> Services { get; set; }

        private void LoadServices()
        {
            var services = _coreDataProvider.GetAllServiceInstancesAssignedToCore(_reactorCoreEntity.Identifier);
            ExecuteOnUiThread(AddResultsToBindableCollection, services);
        }

        private void AddResultsToBindableCollection(IEnumerable<ReactorServiceEntity> services)
        {
            foreach (var vm in services.Select(reactorServiceEntity => new ServiceViewModel(reactorServiceEntity, _reactorCoreEntity)))
                Services.Add(vm);
        }

        private void HandleServiceOrhanedEvent(ServiceOrphaned serviceOrphaned)
        {
            // See if we're displaying the service. If so, remove it.
            ExecuteOnUiThread(() => Services.RemoveAll(s => s.Identifier.Name == serviceOrphaned.ServiceName && s.Identifier.Version.ToString() == serviceOrphaned.Version));
        }
    }
}
